package org.jetnuke.modules.download;

import org.apache.log4j.Logger;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.VelocityContext;
import org.jetnuke.common.ActionForward;
import org.jetnuke.common.IAction;
import org.jetnuke.common.IAdminInfo;
import org.jetnuke.common.IModuleInfo;
import org.jetnuke.common.IUserInfo;
import org.jetnuke.dao.DataAccessDriver;
import org.jetnuke.dao.DownloadDownloadDAO;
import org.jetnuke.entities.DownloadsDownloads;
import org.jetnuke.entities.DownloadsVoteData;
import org.jetnuke.util.JetUtil;

public class Rate implements IAction {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(Rate.class);

	int id;

	String rating;

	String comment = "";

	/**
	 * @param comment
	 *            The comment to set.
	 */
	public void setComment(String comment) {
		this.comment = comment;
	}

	/**
	 * @param id
	 *            The id to set.
	 */
	public void setId(int id) {
		this.id = id;
	}

	/**
	 * @param rating
	 *            The rating to set.
	 */
	public void setRating(String rating) {
		this.rating = rating;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.jetnuke.common.IAction#exec(javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse,
	 *      org.apache.velocity.VelocityContext, org.jetnuke.common.IModuleInfo,
	 *      java.lang.String, org.jetnuke.common.IUserInfo,
	 *      org.jetnuke.common.IAdminInfo)
	 */
	public ActionForward exec(HttpServletRequest request,
			HttpServletResponse response, VelocityContext vc, IModuleInfo info,
			String op, IUserInfo ui, IAdminInfo ai) throws Exception {
		if (logger.isDebugEnabled()) {
			logger
					.debug("exec(HttpServletRequest, HttpServletResponse, VelocityContext, IModuleInfo, String, IUserInfo, IAdminInfo) - start"); //$NON-NLS-1$
		}

		String ip = request.getRemoteAddr();
		boolean pass = true;
		int error = -1;

		if (rating.equals("--")) {
			pass = false;
			error = 0;
		}

		if (pass && ui != null) {
			String uname = ui.getUname();
			int count = DataAccessDriver.getInst().newDownloadDownloadDAO()
					.countUser(id, uname);
			// List ls = downloads_downloadsPeer.doSelect(new Criteria().add(
			// downloads_downloadsPeer.LID, id).add(
			// downloads_downloadsPeer.SUBMITTER, uname));

			// if (!ls.isEmpty()) {//own link
			if (count > 0) {
				pass = false;
				error = 1;
			}
			count = DataAccessDriver.getInst().newDownloadVoteDAO().countUser(
					id, uname);
			// ls = downloads_votedataPeer.doSelect(new Criteria().add(
			// downloads_votedataPeer.RATINGLID, id).add(
			// downloads_votedataPeer.RATINGUSER, uname));
			// if (!ls.isEmpty()) {//already voted
			if (count > 0) {
				pass = false;
				error = 2;
			}

		} else {// anonymous

			GregorianCalendar gc = new GregorianCalendar();
			gc.add(Calendar.DATE, -1);

			int count = DataAccessDriver.getInst().newDownloadVoteDAO()
					.countAnonymous(id, ip, gc.getTime());
			if (count > 0) {
				/*
				 * List ls = downloads_votedataPeer.doSelect(new Criteria().add(
				 * downloads_votedataPeer.RATINGLID, id).add(
				 * downloads_votedataPeer.RATINGUSER, "").add(
				 * downloads_votedataPeer.RATINGHOSTNAME, ip).add(
				 * downloads_votedataPeer.RATINGTIMESTAMP, gc.getTime(),
				 * Criteria.GREATER_EQUAL));
				 */
				// if (!ls.isEmpty()) {//already voted
				pass = false;
				error = 3;
			}
		}
		if (pass) {
			int iRating = Integer.parseInt(rating);
			DownloadsVoteData dt = new DownloadsVoteData();
			// downloads_votedata dt = new downloads_votedata();
			dt.setRATINGLID(id);
			dt.setRATINGTIMESTAMP(new Date());
			dt.setRATING(iRating);
			if (ui != null)
				dt.setRATINGUSER(ui.getUname());
			else
				dt.setRATINGUSER("");
			dt.setRATINGCOMMENTS(comment.trim());
			dt.setRATINGHOSTNAME(request.getRemoteAddr());
			DataAccessDriver.getInst().newDownloadVoteDAO().addNew(dt);
			// dt.save();

			double rate = calcRate(id, 10);// TODO
			DownloadDownloadDAO ddm = DataAccessDriver.getInst()
					.newDownloadDownloadDAO();
			DownloadsDownloads dd = DataAccessDriver.getInst()
					.newDownloadDownloadDAO().retrieveByPK(id);
			// downloads_downloads dd =
			// downloads_downloadsPeer.retrieveByPK(id);
			dd.setTOTALVOTES(dd.getTOTALVOTES() + 1);
			if (comment.trim().length() > 0)
				dd.setTOTALCOMMENTS(dd.getTOTALCOMMENTS() + 1);
			dd.setDOWNLOADRATINGSUMMARY(rate);
			ddm.update(dd);
			// dd.save();
			JetUtil.redirect(vc, response, request.getContextPath()
					+ "/do/download/votevalid");
			// PHPNuke has a much more sophisticated way to calculate the
			// rating.
		} else {
			JetUtil.redirect(vc, response, request.getContextPath()
					+ "/do/download/novalid?error=" + String.valueOf(error));
		}

		if (logger.isDebugEnabled()) {
			logger
					.debug("exec(HttpServletRequest, HttpServletResponse, VelocityContext, IModuleInfo, String, IUserInfo, IAdminInfo) - end"); //$NON-NLS-1$
		}
		return null;
	}

	private double calcRate(int lid, int impact) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("calcRate(int, int) - start"); //$NON-NLS-1$
		}

		double finalRating = 0;
		List ls = DataAccessDriver.getInst().newDownloadVoteDAO()
				.getByRatingLid(lid);
		// List ls=downloads_votedataPeer.doSelect(new
		// Criteria().add(downloads_votedataPeer.RATINGLID,lid));
		int totalVotes = ls.size();
		Iterator it = ls.iterator();
		int anonvotes = 0;

		int anonvoteval = 0;
		int regvoteval = 0;
		while (it.hasNext()) {
			DownloadsVoteData vote = (DownloadsVoteData) it.next();
			int ratingVote = vote.getRATING();
			String user = vote.getRATINGUSER();
			if (user == null || user.length() == 0) {
				anonvotes++;
				anonvoteval += ratingVote;
			} else {
				regvoteval += ratingVote;
			}
		}
		int regvotes = totalVotes - anonvotes;
		if (totalVotes > 0) {
			if (regvotes == 0) {// Only anon
				finalRating = anonvoteval * 1. / anonvotes;
			} else if (anonvotes == 0) { // Only reg
				finalRating = regvoteval * 1. / regvotes;
			} else {
				double avgRU = regvoteval * 1. / regvotes;
				double avgAU = anonvoteval * 1. / anonvotes;
				double impactRU = regvotes;
				double impactAU = anonvotes * 1. / impact;
				finalRating = ((avgRU * impactRU) + (avgAU * impactAU))
						/ (impactRU + impactAU);
			}
		}

		if (logger.isDebugEnabled()) {
			logger.debug("calcRate(int, int) - end"); //$NON-NLS-1$
		}
		return finalRating;
	}

}
